#pragma once

#include "../sys.h"

namespace sfc::net::ip::v4 {

struct Addr {
  u8 _0[4];

  static auto any() -> Addr;
  static auto from_str(Str s) -> Option<Addr>;
};

using Port = u16;

struct Socket : sys::Socket {
  using Addr = v4::Addr;
  using Base = sys::Socket;

  Socket() noexcept;
  explicit Socket(sys::Socket&& s) noexcept;
  explicit Socket(sys::Type type);

  using Base::listen;

  void bind(const Addr& addr, Port port);
  void connect(const Addr& addr, Port port);
  auto accept() -> Socket;
};

struct TcpStream : protected Socket {
  explicit TcpStream(Socket&& s) noexcept;

  using Socket::read;
  using Socket::write;
  static auto connect(const v4::Addr& addr, v4::Port port) -> TcpStream;
};

struct TcpListener : protected Socket {
  explicit TcpListener(Socket&& s) noexcept;

  static auto bind(const v4::Addr& addr, v4::Port port) -> TcpListener;
  auto accept() -> TcpStream;
};

}  // namespace sfc::net::ip::v4
